package aspectos.validador;

import java.beans.PropertyChangeSupport;
import java.util.HashMap;

import uqbar.aspectj.utils.Utils;


public aspect ValidableAspect {

	declare parents : @Validable dominio.validador.* implements ValidableObjectSupport;

	pointcut fieldWrite(ValidableObjectSupport target, Object newValue) : 
		set(* dominio.validador..*)
		&& args(newValue) 
		&& target(@Validable target)
		&& !withincode(*.new(..))
		&& within(@Validable *);

	void around(ValidableObjectSupport target, Object newValue) : fieldWrite(target, newValue) {
		String fieldName = thisJoinPoint.getSignature().getName();
		Object oldValue = Utils.getField(target, fieldName);
		
			target.fieldChanged(fieldName, oldValue, newValue);
			proceed(target, newValue);
	}

	after(ValidableObjectSupport target) : initialization(dominio.validador.*.new(..)) && target(target) {
		target.initialize();
	}
	
	// ***********************************************************
	
	private transient HashMap<String, Validador<?>> ValidableObjectSupport.validadores;
	
	public void ValidableObjectSupport.initialize() {
		this.validadores = new HashMap<String, Validador<?>>(); 
	}
	
	public void ValidableObjectSupport.fieldChanged(String fieldName, Object oldValue, Object newValue) {
	try {
			if (!((Validador<Object>) this.validadores.get(fieldName)).validar(newValue)) {
				throw new ValorInvalidoException();
			}
		} catch(ClassCastException e) {
			throw new ValidadorInvalidoException();
		}
	}
	
	public void ValidableObjectSupport.agregarValidador(String propertyName, Validador<?> validador) {
		this.validadores.put(propertyName, validador);
	}
	
}
